package communication ;

import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import util.Log;
import util.NotFoundException;
import util.Subsystem;
import domain.ForumLogic;

/**
 * a wrapper for Naming to cleanly get the forum.
 * @author idan
 */
public class Client
{
	private final ForumLogic forumLogic ;
	private final String serverUrl ;

	private static Client instance = null ;

	/**
	 * @param url URL of the forum server.
	 * @throws RuntimeException if there was a problem connecting to the URL.
	 * @pre URL is valid.
	 * @post the client is connected to the server at 'url'.
	 */
	public static void configure(final String url) throws RuntimeException
	{
		try
		{
			if (Client.instance == null || !Client.instance.serverUrl.equals(url))
			{
				Client.instance = new Client(url) ;
			}
		}
		catch (NotFoundException e)
		{
			RuntimeException e1 = new RuntimeException("bad url", e) ;
			Log.getLogger(Subsystem.COMMUNICATION).severe(e.getMessage()) ;
			throw e1 ;
		}
		catch (IOException e)
		{
			RuntimeException e1 = new RuntimeException("connection problems", e) ;
			Log.getLogger(Subsystem.COMMUNICATION).severe(e.getMessage()) ;
			throw e1 ;
		}
	}

	/**
	 * @return the client.
	 * @throws RuntimeException if the client is not configured.
	 * @pre client is configured.
	 */
	public static Client instance() throws RuntimeException
	{
		if (Client.instance == null)
		{
			throw new RuntimeException("client is not configured.") ;
		}
		return Client.instance ;
	}

	/**
	 * returns the client, configuring it if necessary.
	 * @param url URL of the forum server.
	 * @return the client.
	 * @pre URL is valid.
	 * @post the client is connected to the server at 'url'.
	 */
	public static Client instance(final String url)
	{
		Client.configure(url) ;
		return Client.instance ;
	}

	private static ForumLogic connectToServer(final String url) throws NotFoundException, IOException
	{
		try
		{
			return (ForumLogic)Naming.lookup(url) ;
		}
		catch (final RemoteException e)
		{
			throw new IOException(e) ;
		}
		catch (final NotBoundException e)
		{
			throw new NotFoundException(url) ;
		}
	}

	/**
	 * set the client up. connect to the server.
	 * @param url URL of the server.
	 * @throws NotFoundException if no server with such URL exists.
	 * @throws IOException if there is a problem communicating with the server.
	 * @pre a server with such URL exists.
	 * @post the client is connected to the server.
	 */
	public Client(final String url) throws NotFoundException, IOException
	{
		this.serverUrl = url ;
		this.forumLogic = Client.connectToServer(this.serverUrl) ;
	}

	/**
	 * @return the forum object implemented by the server.
	 */
	public ForumLogic getForum()
	{
		return this.forumLogic ;
	}
}
